import os
from typing import Optional,List
from fastapi import APIRouter,Path,Query
from pydantic import BaseModel, Field
from enum import Enum

app01 = APIRouter()


class CityName(str,Enum):
    Beijing = '北京'
    Shanhai = '上海'
    Hangzhou = '杭州'

@app01.get("/")
async def index():
    return {
        "name":os.path.basename(__file__)
    }

@app01.get("/path/message")
async def path_parameter():
    return {
        "msg":"message"
    }
# 函数次序就是路由次序，如果这个函数放到前面，那么 /path/message 就会被这个函数先匹配执行
@app01.get("/path/{parameter}",description="路径参数")
async def path_parameter1(parameter:str):
    return {
        "parameter":parameter
    }


@app01.get("/path/enum/{city_name}",description="路径参数-枚举限制数据范围")
async def get_city(city_name:CityName):
    return {
        "city_name":city_name
    }

#如果文件名作为路径参数，由于名字中由 / ,所以要用 :path 来说明
# http://127.0.0.1:8000/chapter01/files//user/config/aa.txt
@app01.get("/files/{file_name:path}")
async def get_file(file_name:str):
    return {
        "file_name":file_name
    }

# 路径参数校验 需要使用到 fastapi 里的 Path
# le 小于等于 ge 大于等于
# lt 小于  gt 大于
@app01.get("/city/{id}")
async def get_city(id:int = Path(...,title="id, 9999>=id>=1000",le=9999,ge=1000)):
    return id

#--------------------------------- 查询参数  ------------------------------------------

@app01.get("/query/pages")
#async def get_pages(page:int,limits:int = None):
async def get_pages(page:int,limits:Optional[int] = None):
    return {
        'page':page,
        'limits':limits
    }

# 查询参数校验 需要使用到 fastapi 里的 Query
# 校验长度、正则匹配
@app01.get("/query/mobile")
async def get_mobile(name:str=Query(...,max_length=10),
                     mobile:str =Query(...,max_length=11,
                                       min_length=11,
                                       regex='^150')):
    return {
        'name':name,
        'mobile':mobile
    }

#多个同名参数传入
#http://127.0.0.1:8000/chapter01/query/books?book=python入门&book=java入门
@app01.get("/query/books")
async def get_books(book:List[str] = Query(default=['书名1','书名2'],alias="book")):
    return book


class Student(BaseModel):
    id: int = Field(...,gt=1000,lt=9999)
    name: str = Field(...,example="姓名")
    address: str = Field(...,max_length=150)

    class Config:
        schema_extra = {
            "example":{
                "id":2101,
                "name":"jack",
                "address":"西湖区XX路XX大厦"
            }
        }

class School(BaseModel):
    id:int
    name:str

# 请求体中包含普通参数
@app01.put("/student")
async def update_student(student:Student):
    return student.json()

# 请求体中包含普通参数
@app01.post("/school")
async def update_school_student(name:str,school:School,student:Student):
    if name == "jack":
        return "OK"
    else:
        return {
            "学校":school,
            "学生":student
        }


# 请求体中嵌套参数

class Animal(BaseModel):
    id: int = Field(ge=1,le=1000,description="动物ID编号")
    name: str
    age: int =Field(ge=1,le=20,description="动物年龄")

class Zoo(BaseModel):
    name: str = Field('XXX动物员',title="名称",description="动物员的名称",max_length=100)
    animals: List[Animal]

@app01.post("/zoo/")
async def update_zoo(zoo:Zoo):
    print(zoo)
    return zoo.json()

class Address(BaseModel):
    city:str
    town:str
    street:str

class Worker(BaseModel):
    id:int
    name:str
    address:Address

class Factory(BaseModel):
    name:str
    worker:Worker



@app01.post("/factory")
async def update_factory(factory:Factory):
    print(factory)
    return factory.json()
